﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;

namespace DARE.Save.DataStructures
{
    public class CRender3DData: ISaveData
    {
        public List<CTerrainData> Terrains = new List<CTerrainData>();
        public List<CNodeData> Nodes = new List<CNodeData>();

        public CPartitionnerData Partitioner = new CPartitionnerData();

        public CCameraMgrData CameraMgr = new CCameraMgrData();
        public CSkyMgrData SkyMgr = new CSkyMgrData();
        public CGameObjectMgrData GameObjectMgr = new CGameObjectMgrData();
        public CEffectMgrData EffectMgr = new CEffectMgrData();

        public int BasicModelSlices;
        public bool ShowModelNode;
        public bool ShowCollision;
        public FillMode FillMode;
        public FillMode CollisionFillMode;
        public bool EnalbePhysics;
        public EType DefaultNodeType;
        public string Name;

        public void FillDataStructure(object render3D)
        {
            CRender3D render = render3D as CRender3D;
            Name = render.Name;
            if (render == null)
                return;
            foreach (CNode node in render.Nodes.Values)
            {
                CNodeData nodeData = new CNodeData();
                nodeData.FillDataStructure(node);
                Nodes.Add(nodeData);
            }
            foreach (CTerrainInfo ti in render.TerrainInfos)
            {
                CTerrainData td = new CTerrainData();
                td.FillDataStructure(ti);
                Terrains.Add(td);
            }
            Partitioner = CDataStructuresMgr.Instance.SaveItem(render.Partitioner) as CPartitionnerData;

            CameraMgr.FillDataStructure(render.CameraMgr);
            SkyMgr.FillDataStructure(render.SkyMgr);
            GameObjectMgr.FillDataStructure(render.GameObjectMgr);
            EffectMgr.FillDataStructure(render.EffectMgr);

            BasicModelSlices = render.BasicModelSlices;
            ShowCollision = render.ShowCollision;
            ShowModelNode = render.ShowModelNode;
            FillMode = render.FillMode;
            CollisionFillMode = render.CollisionFillMode;
            EnalbePhysics = render.EnalbePhysics;
            DefaultNodeType = render.DefaultNodeType;
        }

        public void FillFromDataStructure(out object render3D, params object[] paramsData)
        {
            object partitionner;
            Partitioner.FillFromDataStructure(out partitionner);
            render3D = new CRender3D(Name, partitionner as IPartitioner);
            CRender3D render = render3D as CRender3D;
            if (render == null)
                return;

            render.BasicModelSlices = BasicModelSlices;
            render.ShowCollision = ShowCollision;
            render.ShowModelNode = ShowModelNode;
            render.FillMode = FillMode;
            render.CollisionFillMode = CollisionFillMode;
            render.EnalbePhysics = EnalbePhysics;
            render.DefaultNodeType = DefaultNodeType;

            foreach (CNodeData nodeData in Nodes)
            {
                object node;
                nodeData.FillFromDataStructure(out node, render);
            }

            foreach (CNodeData nodeData in Nodes)
            {
                if (nodeData.parentName != null)
                    render.GetNode(nodeData.Name).SetParent(nodeData.parentName);
                render.GetNode(nodeData.Name).SetPosition(nodeData.position, CNode.ESpace.WORLD);
                render.GetNode(nodeData.Name).SetOrientation(nodeData.orientation, CNode.ESpace.WORLD);
                render.GetNode(nodeData.Name).SetScale(nodeData.scale);
            }

            object cam;
            CameraMgr.FillFromDataStructure(out cam, render);
            render.CameraMgr = cam as CCameraMgr;
            object sky;
            SkyMgr.FillFromDataStructure(out sky, render);
            render.SkyMgr = sky as CSkyMgr;
            object gom;
            if (paramsData.Length > 0 && paramsData[0] is CScene)
            {
                GameObjectMgr.FillFromDataStructure(out gom, render, (paramsData[0] as CScene).ActiveHudSystem);
                render.GameObjectMgr = gom as CGameObjectMgr;
            }
            object em;
            EffectMgr.FillFromDataStructure(out em, render);
            render.EffectMgr = em as CEffectMgr;

            foreach (CTerrainData terrain in Terrains)
            {
                object terrainNode;
                terrain.FillFromDataStructure(out terrainNode);
                render.AddNode(terrainNode as CNode);
            }
        }
    }
}
